package com.hqd.ch03.v39.web.servlet.mvc.method.annotation;

import com.hqd.ch03.v39.utils.StringUtils;
import com.hqd.ch03.v39.web.context.request.NativeWebRequest;
import com.hqd.ch03.v39.web.context.request.ServletWebRequest;
import com.hqd.ch03.v39.web.http.HttpHeaders;
import com.hqd.ch03.v39.web.method.HandlerMethod;
import com.hqd.ch03.v39.web.method.support.HandlerMethodReturnValueHandlerComposite;
import com.hqd.ch03.v39.web.servlet.mvc.method.InvocableHandlerMethod;
import com.hqd.ch03.v39.web.servlet.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {

    private HandlerMethodReturnValueHandlerComposite returnValueHandlers;

    public ServletInvocableHandlerMethod(Object handler, Method method) {
        super(handler, method);
    }


    public ServletInvocableHandlerMethod(HandlerMethod handlerMethod) {
        super(handlerMethod);
    }


    public void setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite returnValueHandlers) {
        this.returnValueHandlers = returnValueHandlers;
    }


    public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
                                Object... providedArgs) throws Exception {

        Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);

        if (returnValue == null) {
            if (isRequestNotModified(webRequest) || mavContainer.isRequestHandled()) {
                disableContentCachingIfNecessary(webRequest);
                mavContainer.setRequestHandled(true);
                return;
            }
        }

        mavContainer.setRequestHandled(false);
        try {
            this.returnValueHandlers.handleReturnValue(
                    returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
        } catch (Exception ex) {
            throw ex;
        }
    }

    public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mav,
                                   Object... providedArgs) throws Exception {

        Object[] args = getMethodArgumentValues(request, mav, providedArgs);
        return doInvoke(args);
    }

    private boolean isRequestNotModified(ServletWebRequest webRequest) {
        return webRequest.isNotModified();
    }

    private void disableContentCachingIfNecessary(ServletWebRequest webRequest) {
        if (isRequestNotModified(webRequest)) {
            HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
            if (StringUtils.hasText(response.getHeader(HttpHeaders.ETAG))) {
                HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
            }
        }
    }
}
